<template>
  <div class="schedule-analysis">
    <div class="control-panel">
      <div class="time-control">
        <DatePicker
          type="datetime"
          v-model="currentTime"
          :options="timeOptions"
          :editable="false"
          format="yyyy-MM-dd HH:mm:ss"
          placeholder="选择时间"
          style="width: 200px"
          @on-change="onTimeChange"
        />
        <ButtonGroup class="play-controls">
          <Button @click="handlePlayPause">
            <Icon :type="isPlaying ? 'ios-pause' : 'ios-play'" />
          </Button>
          <Button @click="handleStop">
            <Icon type="ios-square" />
          </Button>
        </ButtonGroup>
        <Select
          v-model="playSpeed"
          style="width: 100px"
          @on-change="onSpeedChange"
        >
          <Option
            v-for="speed in speedOptions"
            :key="speed.value"
            :value="speed.value"
          >
            {{ speed.label }}
          </Option>
        </Select>
        <Input
          v-model="scheduleNum"
          placeholder="请输入调度编号"
          style="width: 200px"
        />
        <Button type="primary" @click="loadScheduleData">确定</Button>
      </div>
      <div class="progress-control">
        <span class="time-label">{{ formatTime(startTime) }}</span>
        <Slider
          v-model="progressValue"
          :step="1"
          :min="0"
          :max="totalSeconds"
          style="flex: 1; margin: 0 16px"
          @on-change="onProgressChange"
        />
        <span class="time-label">{{ formatTime(endTime) }}</span>
      </div>
    </div>

    <div class="main-content">
      <div ref="container" class="graph-container"></div>
    </div>

    <!-- 底部滑出面板 -->
    <div class="detail-panel" :class="{ 'panel-show': showDetailPanel }">
      <div class="panel-header">
        <span>工件明细</span>
        <Button icon="md-close" size="small" @click="showDetailPanel = false" />
      </div>
      <div class="panel-content">
        <Table :columns="tableColumns" :data="tableData" :height="300">
          <template slot-scope="{ row }" slot="status">
            <Tag :color="row.status === 'processing' ? 'success' : 'primary'">
              {{ row.status === 'processing' ? '加工中' : '运输中' }}
            </Tag>
          </template>
        </Table>
      </div>
    </div>

    <!-- 时序图面板 -->
    <div class="timeline-panel" :class="{ 'panel-show': showTimelinePanel }">
      <div class="panel-header">
        <span>时序图明细</span>
        <Button
          icon="md-close"
          size="small"
          @click="showTimelinePanel = false"
        />
      </div>
      <div class="panel-content">
        <div class="timeline-container">
          <div
            v-for="workpiece in timelineData"
            :key="workpiece.workPieceID"
            class="timeline-item"
          >
            <div class="timeline-header">
              <span class="workpiece-id">工件 {{ workpiece.workPieceID }}</span>
              <span class="total-time">总耗时: {{ workpiece.totalTime }}</span>
            </div>
            <div class="timeline-content">
              <div
                v-for="(detail, index) in workpiece.details"
                :key="index"
                class="timeline-step"
              >
                <div class="step-info">
                  <span class="station-name">{{
                    getStationName(detail.stationID)
                  }}</span>
                  <span class="time">{{
                    formatTimeRange(detail.startTime, detail.endTime)
                  }}</span>
                </div>
                <div class="step-status" :class="detail.status">
                  {{ detail.status === 'processing' ? '加工' : '运输' }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 底部按钮组 -->
    <div class="bottom-buttons">
      <div class="detail-trigger" @click="showDetailPanel = true">
        <Icon type="md-list" />
        <span>查看工件明细</span>
      </div>
      <div class="timeline-trigger" @click="showTimelinePanel = true">
        <Icon type="md-trending-up" />
        <span>查看时序图</span>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { DagreLayout } from '@antv/layout';
import { Graph, Node } from '@antv/x6';
import { Component, Vue, Watch } from 'vue-property-decorator';
import * as configData from './config';

interface Station {
  name: string;
  nextNodes: string[];
}

interface Workshop {
  stations: {
    [key: string]: Station;
  };
}

interface WorkpieceDetail {
  workshopID: string;
  stationID: string;
  startTime: string;
  endTime: string;
  status: 'processing' | 'transfer';
  parameters?: string;
}

interface Workpiece {
  workPieceID: string;
  details: WorkpieceDetail[];
}

interface ScheduleInfo {
  startTime: string;
  endTime: string;
}

interface ScheduleResultConfig {
  info: ScheduleInfo;
  workpieces: Workpiece[];
}

interface WorkpieceStatus {
  workPieceID: string;
  stationID: string;
  status: 'processing' | 'transfer';
  parameters?: string;
}

@Component({
  name: 'ScheduleAnalysis'
})
export default class ScheduleAnalysis extends Vue {
  private graph: Graph | null = null;

  private nodes: { [key: string]: Node } = {};

  private workshopsConfig: Workshop[] | null = null;

  private scheduleResultConfig: ScheduleResultConfig | null = null;

  private currentTime: Date | null = null;

  private isPlaying: boolean = false;

  private playSpeed: number = 1;

  private playTimer: number | null = null;

  private isLoading: boolean = true;

  private scheduleNum: string = '1743115903680';

  private speedOptions = [
    { label: '0.5x', value: 0.5 },
    { label: '1x', value: 1 },
    { label: '2x', value: 2 },
    { label: '5x', value: 5 },
    { label: '10x', value: 10 },
    { label: '20x', value: 20 }
  ];

  private timeOptions = {
    disabledDate: (date: Date) => {
      if (!this.scheduleResultConfig) return true;
      const startTime = new Date(this.scheduleResultConfig.info.startTime);
      const endTime = new Date(this.scheduleResultConfig.info.endTime);
      return date < startTime || date > endTime;
    }
  };

  private showDetailPanel: boolean = false;

  private showTimelinePanel: boolean = false;

  private timelineData: any[] = [];

  private tableColumns = [
    {
      title: '工件ID',
      key: 'workPieceID',
      width: 120
    },
    {
      title: '当前工位',
      key: 'stationName',
      width: 150
    },
    {
      title: '状态',
      slot: 'status',
      width: 100
    },
    {
      title: '开始时间',
      key: 'startTime',
      width: 180
    },
    {
      title: '结束时间',
      key: 'endTime',
      width: 180
    },
    {
      title: '参数',
      key: 'parameters',
      ellipsis: true
    }
  ];

  private tableData: any[] = [];

  private currentTooltip: HTMLElement | null = null;

  async created() {
    console.log('Component created');
  }

  mounted() {
    this.loadScheduleData();
  }

  private async loadScheduleData() {
    console.log('Loading schedule data...');
    try {
      this.isLoading = true;
      this.stopPlay(); // 停止当前播放
      this.clearCurrentData(); // 清除当前数据

      console.log('Calling getConfig with scheduleNum:', this.scheduleNum);
      const res = await configData.getConfig(this.scheduleNum);
      console.log('getConfig response:', res);

      // 验证数据格式
      if (!this.validateConfigData(res)) {
        console.error('Invalid config data format');
        this.$Message.error('数据格式无效');
        throw new Error('Invalid config data format');
      }

      this.workshopsConfig = res.workshopsConfig;
      this.scheduleResultConfig = res.scheduleResultConfig;

      // 将UTC时间转换为中国时区时间
      const startTime = new Date(res.scheduleResultConfig.info.startTime);

      // 计算实际的结束时间（最后一个工件的最后一个步骤的结束时间）
      let actualEndTime = new Date(res.scheduleResultConfig.info.startTime);
      res.scheduleResultConfig.workpieces.forEach(workpiece => {
        if (workpiece.details.length > 0) {
          const lastDetail = workpiece.details[workpiece.details.length - 1];
          const lastEndTime = new Date(lastDetail.endTime);
          if (lastEndTime > actualEndTime) {
            actualEndTime = lastEndTime;
          }
        }
      });

      // 更新调度结果中的时间
      this.scheduleResultConfig.info.startTime = startTime.toISOString();
      this.scheduleResultConfig.info.endTime = actualEndTime.toISOString();

      // 更新工件详情中的时间
      this.scheduleResultConfig.workpieces.forEach(workpiece => {
        workpiece.details.forEach(detail => {
          const detailStartTime = new Date(detail.startTime);
          const detailEndTime = new Date(detail.endTime);
          detail.startTime = detailStartTime.toISOString();
          detail.endTime = detailEndTime.toISOString();
        });
      });

      this.currentTime = startTime;
      console.log('Config data initialized successfully');

      // 等待DOM更新完成
      await this.$nextTick();
      console.log('DOM updated');

      // 确保DOM元素已经渲染
      const container = this.$refs.container as HTMLElement;
      if (!container) {
        console.error('Container element not found');
        throw new Error('Container element not found');
      }

      // 确保容器有尺寸
      container.style.width = '100%';
      container.style.height = '100%';
      container.style.minHeight = '500px';

      // 初始化图表
      setTimeout(() => {
        try {
          console.log('Initializing graph...');
          this.initGraph();
          this.updateTimelineData();
          console.log('Graph initialized successfully');
          this.$Message.success('数据加载成功');
        } catch (error) {
          console.error('Error initializing graph:', error);
          this.$Message.error('图表初始化失败');
        }
      }, 500);
    } catch (error) {
      console.error('Error loading schedule data:', error);
      this.$Message.error('数据加载失败');
    } finally {
      this.isLoading = false;
      console.log('Schedule data loading completed');
    }
  }

  private clearCurrentData() {
    if (this.graph) {
      this.graph.dispose();
      this.graph = null;
    }
    this.nodes = {};
    this.timelineData = [];
    this.tableData = [];
  }

  private validateConfigData(res: any): boolean {
    if (!res || typeof res !== 'object') return false;
    if (!Array.isArray(res.workshopsConfig)) return false;
    if (
      !res.scheduleResultConfig ||
      typeof res.scheduleResultConfig !== 'object'
    )
      return false;
    if (!res.scheduleResultConfig.info || !res.scheduleResultConfig.workpieces)
      return false;
    if (
      !res.scheduleResultConfig.info.startTime ||
      !res.scheduleResultConfig.info.endTime
    )
      return false;
    return true;
  }

  beforeDestroy() {
    this.stopPlay();
    if (this.graph) {
      this.graph.dispose();
    }
  }

  @Watch('currentTime')
  onCurrentTimeChange() {
    if (this.scheduleResultConfig) {
      this.updateWorkpiecePositions();
    }
  }

  private initGraph() {
    if (!this.workshopsConfig || !this.scheduleResultConfig) {
      return;
    }

    this.graph = new Graph({
      container: this.$refs.container as HTMLElement,
      grid: true,
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: ['ctrl', 'meta']
      },
      connecting: {
        snap: true,
        allowBlank: false,
        allowLoop: false,
        highlight: true
      },
      panning: {
        enabled: true,
        eventTypes: ['leftMouseDown', 'mouseWheel']
      }
    });

    // 注册节点鼠标事件
    this.graph.on('node:mouseenter', ({ node, e }) => {
      const workpieces = this.getNodeWorkpieces(node.id);
      if (workpieces.length > 0) {
        const content = this.createTooltipContent(workpieces);
        const tooltip = document.createElement('div');
        tooltip.className = 'node-tooltip';
        tooltip.innerHTML = content;

        // 获取鼠标位置
        const { clientX, clientY } = e;

        // 设置 tooltip 位置
        tooltip.style.position = 'fixed';
        tooltip.style.left = `${clientX + 10}px`; // 鼠标右侧10px
        tooltip.style.top = `${clientY}px`;
        tooltip.style.zIndex = '10000'; // 确保在最上层

        // 检查是否超出右侧边界
        document.body.appendChild(tooltip);
        const tooltipRect = tooltip.getBoundingClientRect();
        if (tooltipRect.right > window.innerWidth) {
          tooltip.style.left = `${clientX - tooltipRect.width - 10}px`; // 改为显示在鼠标左侧
        }

        // 检查是否超出底部边界
        if (tooltipRect.bottom > window.innerHeight) {
          tooltip.style.top = `${clientY - tooltipRect.height}px`;
        }

        this.currentTooltip = tooltip;
      }
    });

    this.graph.on('node:mouseleave', () => {
      if (this.currentTooltip && document.body.contains(this.currentTooltip)) {
        document.body.removeChild(this.currentTooltip);
        this.currentTooltip = null;
      }
    });

    // 注册视图变换事件，在缩放或平移时隐藏 tooltip
    this.graph.on('transform', () => {
      if (this.currentTooltip && document.body.contains(this.currentTooltip)) {
        document.body.removeChild(this.currentTooltip);
        this.currentTooltip = null;
      }
    });

    this.renderWorkshops();
  }

  private renderWorkshops() {
    if (!this.graph) {
      return;
    }

    // 检查数据是否存在
    if (!this.workshopsConfig || !Array.isArray(this.workshopsConfig)) {
      return;
    }

    // 清除现有内容
    this.graph.clearCells();
    this.nodes = {};

    const nodeData: any[] = [];
    const edgeData: any[] = [];
    const nodeIds = new Set<string>();

    // 遍历工作站配置并创建节点数据
    this.workshopsConfig.forEach(workshop => {
      if (
        !workshop ||
        !workshop.stations ||
        typeof workshop.stations !== 'object'
      ) {
        return;
      }

      Object.entries(workshop.stations).forEach(([stationID, station]) => {
        if (!station || typeof station !== 'object') {
          return;
        }

        nodeIds.add(stationID);
        nodeData.push({
          id: stationID,
          shape: 'rect',
          width: 180,
          height: 100,
          label: `${station.name || 'Unknown'}\n\n(${stationID})`,
          attrs: {
            body: {
              fill: '#fff',
              stroke: '#333',
              strokeWidth: 2,
              rx: 8,
              ry: 8
            },
            label: {
              fontSize: 24,
              fill: '#000',
              fontWeight: 600,
              refY: 0.4,
              letterSpacing: 0.5
            }
          }
        });

        if (Array.isArray(station.nextNodes)) {
          station.nextNodes.forEach(nextId => {
            if (nextId) {
              edgeData.push({
                source: stationID,
                target: nextId,
                attrs: {
                  line: {
                    stroke: '#333',
                    strokeWidth: 2
                  }
                }
              });
            }
          });
        }
      });
    });

    if (nodeData.length === 0) {
      return;
    }

    const layout = new DagreLayout({
      type: 'dagre',
      rankdir: 'LR',
      align: 'UL',
      ranksep: 60,
      nodesep: 50,
      controlPoints: true
    });

    try {
      const containerWidth = (this.$refs.container as HTMLElement).clientWidth;
      const containerHeight = (this.$refs.container as HTMLElement)
        .clientHeight;
      const totalNodes = nodeData.length;
      const maxNodesPerRow = 8;
      const rows = Math.ceil(totalNodes / maxNodesPerRow);

      nodeData.forEach((node, index) => {
        const row = Math.floor(index / maxNodesPerRow);
        const col = index % maxNodesPerRow;
        node.x = col * 210;
        node.y = row * 130;
      });

      const layoutResult = layout.layout({
        nodes: nodeData,
        edges: edgeData.filter(
          edge => nodeIds.has(edge.source) && nodeIds.has(edge.target)
        )
      });

      layoutResult.nodes.forEach((node: any) => {
        try {
          const { x, y, ...nodeConfig } = node;
          const graphNode = this.graph!.addNode({
            ...nodeConfig,
            position: { x, y }
          });
          this.nodes[node.id] = graphNode;
        } catch (error) {
          console.error('Error adding node:', error);
        }
      });

      layoutResult.edges.forEach((edge: any) => {
        try {
          if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
            this.graph!.addEdge(edge);
          }
        } catch (error) {
          console.error('Error adding edge:', error);
        }
      });

      this.addZoomControl();
      this.graph.centerContent();
      this.graph.zoomToFit({ padding: 50 });
      this.updateWorkpiecePositions();
    } catch (error) {
      console.error('Error in layout:', error);
    }
  }

  private addZoomControl() {
    if (!this.graph) return;

    const container = this.$refs.container as HTMLElement;
    const controlDiv = document.createElement('div');
    controlDiv.style.position = 'absolute';
    controlDiv.style.right = '20px';
    controlDiv.style.top = '20px';
    controlDiv.style.transform = 'none';
    controlDiv.style.zIndex = '1000';
    controlDiv.style.display = 'flex';
    controlDiv.style.flexDirection = 'row';
    controlDiv.style.gap = '8px';
    controlDiv.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
    controlDiv.style.padding = '6px 10px';
    controlDiv.style.borderRadius = '20px';
    controlDiv.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';

    const createButton = (text: string, onClick: () => void) => {
      const button = document.createElement('button');
      button.textContent = text;
      button.style.padding = '4px 12px'; // 减小内边距
      button.style.cursor = 'pointer';
      button.style.backgroundColor = '#fff';
      button.style.border = '1px solid #ddd';
      button.style.borderRadius = '16px'; // 圆角按钮
      button.style.fontSize = '13px';
      button.style.color = '#333';
      button.style.width = 'auto'; // 自适应宽度
      button.style.minWidth = '60px'; // 最小宽度
      button.style.transition = 'all 0.3s ease';
      button.style.display = 'flex';
      button.style.alignItems = 'center';
      button.style.justifyContent = 'center';
      button.style.height = '28px'; // 固定高度

      button.addEventListener('mouseover', () => {
        button.style.backgroundColor = '#f5f5f5';
        button.style.borderColor = '#ccc';
      });

      button.addEventListener('mouseout', () => {
        button.style.backgroundColor = '#fff';
        button.style.borderColor = '#ddd';
      });

      button.addEventListener('click', onClick);
      return button;
    };

    const zoomInBtn = createButton('放大', () => {
      const scale = this.graph!.scale();
      this.graph!.scale(scale.sx + 0.1, scale.sy + 0.1);
    });

    const zoomOutBtn = createButton('缩小', () => {
      const scale = this.graph!.scale();
      this.graph!.scale(
        Math.max(0.1, scale.sx - 0.1),
        Math.max(0.1, scale.sy - 0.1)
      );
    });

    const fitBtn = createButton('适应屏幕', () => {
      this.graph!.zoomToFit({ padding: 50 });
    });

    controlDiv.appendChild(zoomInBtn);
    controlDiv.appendChild(zoomOutBtn);
    controlDiv.appendChild(fitBtn);

    // 移除旧的控制按钮（如果存在）
    const oldControl = container.querySelector('.zoom-control');
    if (oldControl) {
      container.removeChild(oldControl);
    }

    controlDiv.className = 'zoom-control';
    container.appendChild(controlDiv);
  }

  private handlePlayPause() {
    if (this.isPlaying) {
      this.stopPlay();
    } else {
      this.startPlay();
    }
    this.isPlaying = !this.isPlaying;
  }

  private handleStop() {
    this.stopPlay();
    if (this.scheduleResultConfig) {
      this.currentTime = new Date(this.scheduleResultConfig.info.startTime);
    }
    this.isPlaying = false;
    this.$nextTick(() => {
      this.updateWorkpiecePositions();
    });
  }

  private startPlay() {
    if (this.playTimer) return;

    const baseInterval = 50; // 基础更新间隔为50ms
    let lastUpdateTime = Date.now();

    this.playTimer = window.setInterval(() => {
      const now = Date.now();
      const realElapsed = now - lastUpdateTime; // 实际经过的时间（毫秒）
      lastUpdateTime = now;

      // 根据实际经过的时间和播放速度计算模拟时间增量
      const simulatedElapsed = realElapsed * this.playSpeed;

      const nextTime = new Date(this.currentTime!.getTime() + simulatedElapsed);

      if (nextTime > this.endTime) {
        this.stopPlay();
        this.isPlaying = false;
        return;
      }
      this.currentTime = nextTime;

      // 使用 requestAnimationFrame 确保在下一帧更新节点状态
      requestAnimationFrame(() => {
        this.updateWorkpiecePositions();
      });
    }, baseInterval);
  }

  private stopPlay() {
    if (this.playTimer) {
      clearInterval(this.playTimer);
      this.playTimer = null;
    }
  }

  private onTimeChange() {
    this.$nextTick(() => {
      this.updateWorkpiecePositions();
    });
  }

  private onSpeedChange(value: number) {
    this.playSpeed = value;
    if (this.isPlaying) {
      this.stopPlay();
      this.startPlay();
    }
  }

  private updateWorkpiecePositions() {
    if (!this.graph) return;

    // 重置所有节点的边框颜色为默认颜色
    Object.values(this.nodes).forEach(node => {
      node.setAttrByPath('body/stroke', '#333');
    });

    // 获取当前时间点的工件状态
    const currentStatus = this.getCurrentWorkpieceStatus();

    // 创建一个Set来跟踪有工件加工的节点
    const processingNodes = new Set<string>();

    // 检查每个工件的状态
    currentStatus.forEach(status => {
      if (status.status === 'processing') {
        processingNodes.add(status.stationID);
      }
    });

    // 为有工件加工的节点设置高亮颜色
    processingNodes.forEach(stationID => {
      const node = this.nodes[stationID];
      if (node) {
        node.setAttrByPath('body/stroke', '#faad14');
      }
    });

    // 更新表格数据
    this.updateTableData(currentStatus);
  }

  private getCurrentWorkpieceStatus(): WorkpieceStatus[] {
    if (!this.scheduleResultConfig || !this.currentTime) {
      return [];
    }

    const status: WorkpieceStatus[] = [];

    this.scheduleResultConfig.workpieces.forEach(workpiece => {
      // 获取当前正在进行的步骤
      const currentDetails = workpiece.details.filter(detail => {
        const startTime = new Date(detail.startTime);
        const endTime = new Date(detail.endTime);
        return (
          this.currentTime.getTime() >= startTime.getTime() &&
          this.currentTime.getTime() <= endTime.getTime()
        );
      });

      // 添加当前正在进行的步骤
      currentDetails.forEach(detail => {
        status.push({
          workPieceID: workpiece.workPieceID,
          stationID: detail.stationID,
          status: detail.status,
          parameters: detail.parameters
        });
      });
    });

    return status;
  }

  private get startTime(): Date {
    if (!this.scheduleResultConfig) return new Date();
    return new Date(this.scheduleResultConfig.info.startTime);
  }

  private get endTime(): Date {
    if (!this.scheduleResultConfig) return new Date();
    return new Date(this.scheduleResultConfig.info.endTime);
  }

  private get totalSeconds(): number {
    return Math.floor(
      (this.endTime.getTime() - this.startTime.getTime()) / 1000
    );
  }

  private get progressValue(): number {
    if (!this.currentTime) return 0;
    return Math.floor(
      (this.currentTime.getTime() - this.startTime.getTime()) / 1000
    );
  }

  private set progressValue(value: number) {
    const newTime = new Date(this.startTime!.getTime() + value * 1000);
    if (newTime <= this.endTime) {
      this.currentTime = newTime;
    }
  }

  private formatTime(date: Date): string {
    // 直接使用 ISO 字符串并移除 Z 后缀
    return date.toISOString().replace('Z', '');
  }

  private onProgressChange(value: number) {
    this.progressValue = value;
  }

  // 获取工位名称的方法
  private getStationName(stationID: string): string {
    for (const workshop of this.workshopsConfig) {
      const station = workshop.stations[stationID];
      if (station) {
        return station.name || stationID;
      }
    }
    return stationID;
  }

  // 添加更新表格数据的方法
  private updateTableData(currentStatus: WorkpieceStatus[]) {
    if (!this.scheduleResultConfig) return;

    this.tableData = currentStatus.map(status => {
      const workpiece = this.scheduleResultConfig!.workpieces.find(
        wp => wp.workPieceID === status.workPieceID
      );
      const currentDetail = workpiece?.details.find(
        detail =>
          detail.stationID === status.stationID &&
          new Date(detail.startTime) <= this.currentTime! &&
          new Date(detail.endTime) >= this.currentTime!
      );

      return {
        workPieceID: status.workPieceID,
        stationID: status.stationID,
        stationName: this.getStationName(status.stationID),
        status: status.status,
        startTime: currentDetail
          ? new Date(currentDetail.startTime).toISOString().replace('Z', '')
          : '',
        endTime: currentDetail
          ? new Date(currentDetail.endTime).toISOString().replace('Z', '')
          : '',
        parameters: status.parameters || '-'
      };
    });
  }

  // 添加获取节点工件的方法
  private getNodeWorkpieces(nodeId: string): any[] {
    return this.getCurrentWorkpieceStatus().filter(
      status => status.stationID === nodeId
    );
  }

  // 修改tooltip内容，显示更详细的信息
  private createTooltipContent(workpieces: any[]): string {
    if (workpieces.length === 0) return '';

    const stationName = this.getStationName(workpieces[0].stationID);
    let content = `
      <div class="tooltip-header">
        <strong>${stationName}</strong>
        <span class="count">共 ${workpieces.length} 个工件</span>
      </div>
      <div class="tooltip-content">
    `;

    workpieces.forEach(wp => {
      const statusText = wp.status === 'processing' ? '加工中' : '运输中';
      const statusClass =
        wp.status === 'processing' ? 'status-process' : 'status-transfer';

      // 获取当前工件的详细信息
      const workpiece = this.scheduleResultConfig?.workpieces.find(
        w => w.workPieceID === wp.workPieceID
      );

      // 获取当前工件的当前步骤
      const currentDetail = workpiece?.details.find(
        detail =>
          detail.stationID === wp.stationID &&
          new Date(detail.startTime) <= this.currentTime! &&
          new Date(detail.endTime) >= this.currentTime!
      );

      const startTime = currentDetail ? currentDetail.startTime : '';
      const endTime = currentDetail ? currentDetail.endTime : '';

      content += `
        <div class="workpiece-item">
          <span class="id">工件 ${wp.workPieceID}</span>
          <span class="status ${statusClass}">${statusText}</span>
          <div class="time-info">
            <span>开始: ${startTime}</span>
            <span>结束: ${endTime}</span>
          </div>
        </div>
      `;
    });

    content += '</div>';
    return content;
  }

  // 添加计算时序图数据的方法
  private updateTimelineData() {
    if (!this.scheduleResultConfig) return;

    this.timelineData = this.scheduleResultConfig.workpieces.map(workpiece => {
      const details = workpiece.details.map(d => ({
        ...d,
        startTime: new Date(d.startTime),
        endTime: new Date(d.endTime),
        stationID: d.stationID
      }));

      const totalTime = this.calculateTotalTime(details);

      return {
        workPieceID: workpiece.workPieceID,
        totalTime,
        details
      };
    });
  }

  private calculateTotalTime(details: any[]): string {
    if (details.length === 0) return '0分钟';

    // 确保我们使用的是最早的开始时间和最晚的结束时间
    let minStartTime = new Date(details[0].startTime).getTime();
    let maxEndTime = new Date(details[0].endTime).getTime();

    details.forEach(detail => {
      const startTime = new Date(detail.startTime).getTime();
      const endTime = new Date(detail.endTime).getTime();
      minStartTime = Math.min(minStartTime, startTime);
      maxEndTime = Math.max(maxEndTime, endTime);
    });

    const diffMinutes = Math.round((maxEndTime - minStartTime) / (1000 * 60));
    return `${diffMinutes}分钟`;
  }

  // 格式化时间范围
  private formatTimeRange(startTime: Date, endTime: Date): string {
    const formatTime = (date: Date) => {
      // 直接使用 ISO 字符串并移除 Z 后缀
      return date.toISOString().replace('Z', '');
    };
    return `${formatTime(startTime)} - ${formatTime(endTime)}`;
  }
}
</script>

<style lang="less">
.schedule-analysis {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;

  .control-panel {
    padding: 16px;
    background: #fff;
    border-bottom: 1px solid #e8e8e8;

    .time-control {
      display: flex;
      align-items: center;
      gap: 16px;

      .play-controls {
        margin: 0 16px;
      }
    }

    .progress-control {
      display: flex;
      align-items: center;
      margin-top: 16px;
      padding: 0 16px;

      .time-label {
        font-size: 12px;
        color: #666;
        white-space: nowrap;
      }
    }
  }

  .main-content {
    flex: 1;
    position: relative;
    overflow: hidden;
    min-height: 500px;

    .graph-container {
      width: 100%;
      height: 100%;
      background: #fafafa;
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
  }

  .detail-panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: -360px;
    height: 360px;
    background: #fff;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.15);
    transition: bottom 0.3s ease-in-out;
    z-index: 1000;

    &.panel-show {
      bottom: 0;
    }

    .panel-header {
      height: 40px;
      padding: 0 16px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid #e8e8e8;
      background: #fafafa;

      span {
        font-size: 14px;
        font-weight: 500;
        color: #333;
      }
    }

    .panel-content {
      height: calc(100% - 40px);
      padding: 16px;
      overflow: hidden;
    }
  }

  .timeline-panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: -360px;
    height: 360px;
    background: #fff;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.15);
    transition: bottom 0.3s ease-in-out;
    z-index: 1000;

    &.panel-show {
      bottom: 0;
    }

    .panel-header {
      height: 40px;
      padding: 0 16px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid #e8e8e8;
      background: #fafafa;

      span {
        font-size: 14px;
        font-weight: 500;
        color: #333;
      }
    }

    .panel-content {
      height: calc(100% - 40px);
      padding: 16px;
      overflow-x: auto;
      overflow-y: hidden;

      .timeline-container {
        display: flex;
        gap: 24px;
        padding: 8px;
        min-width: min-content;

        .timeline-item {
          flex: 0 0 300px;
          padding: 16px;
          background: #fafafa;
          border-radius: 8px;
          height: 280px;
          display: flex;
          flex-direction: column;

          .timeline-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
            padding-bottom: 8px;
            border-bottom: 1px solid #e8e8e8;

            .workpiece-id {
              font-size: 15px;
              font-weight: 600;
              color: #f30;
            }

            .total-time {
              font-size: 13px;
              color: #666;
            }
          }

          .timeline-content {
            flex: 1;
            overflow-y: auto;
            padding-right: 8px;

            &::-webkit-scrollbar {
              width: 4px;
            }

            &::-webkit-scrollbar-thumb {
              background: #ddd;
              border-radius: 2px;
            }

            .timeline-step {
              display: flex;
              justify-content: space-between;
              align-items: center;
              padding: 8px 0;
              position: relative;

              &:not(:last-child)::after {
                content: '';
                position: absolute;
                left: 8px;
                top: 100%;
                width: 2px;
                height: 8px;
                background: #e8e8e8;
              }

              .step-info {
                display: flex;
                flex-direction: column;
                gap: 4px;

                .station-name {
                  font-size: 14px;
                  color: #333;
                  font-weight: 500;
                }

                .time {
                  font-size: 12px;
                  color: #666;
                }
              }

              .step-status {
                padding: 4px 12px;
                border-radius: 12px;
                font-size: 12px;
                font-weight: 500;

                &.process {
                  background: #f6ffed;
                  color: #389e0d;
                  border: 1px solid #b7eb8f;
                }

                &.transfer {
                  background: #e6f7ff;
                  color: #096dd9;
                  border: 1px solid #91d5ff;
                }
              }
            }
          }
        }
      }
    }
  }

  .bottom-buttons {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: 20px;
    display: flex;
    gap: 16px;
    z-index: 999;

    .detail-trigger,
    .timeline-trigger {
      padding: 8px 16px;
      background: #fff;
      border-radius: 20px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 8px;
      transition: all 0.3s ease;

      &:hover {
        background: #f5f5f5;
      }

      .ivu-icon {
        font-size: 16px;
      }

      span {
        font-size: 14px;
        color: #333;
      }
    }
  }
}

.node-tooltip {
  position: fixed;
  background: #ffffff;
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  padding: 16px;
  z-index: 10000;
  pointer-events: none;
  max-width: 300px;
  font-size: 12px;
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  border: 1px solid #e8e8e8;

  .tooltip-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid #e8e8e8;

    strong {
      font-size: 15px;
      color: #f30;
      font-weight: 600;
      letter-spacing: 0.3px;
    }

    .count {
      color: #f30;
      background: #fff1f0;
      padding: 3px 10px;
      border-radius: 12px;
      font-size: 12px;
      font-weight: 500;
    }
  }

  .tooltip-content {
    .workpiece-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 6px 8px;
      margin: 2px 0;
      border-radius: 6px;
      transition: all 0.2s ease;

      .id {
        color: #f30;
        margin-right: 12px;
        font-weight: 500;
      }

      .status {
        padding: 3px 10px;
        border-radius: 12px;
        font-size: 11px;
        white-space: nowrap;
        font-weight: 500;
        letter-spacing: 0.3px;

        &.status-process {
          background: #f6ffed;
          color: #389e0d;
          border: 1px solid #b7eb8f;
        }

        &.status-transfer {
          background: #e6f7ff;
          color: #096dd9;
          border: 1px solid #91d5ff;
        }
      }

      &:hover {
        background: #fafafa;
      }
    }
  }
}
</style>
